package com.chat.server;

import com.chat.protocol.IMDecoder;
import com.chat.protocol.IMEncoder;
import com.chat.server.handler.HttpHandler;
import com.chat.server.handler.SocketHandler;
import com.chat.server.handler.WebSocketHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @author Chenjie
 * @Title: ChatServer
 * @Package com.chat.server
 * @Description:
 * @date 2017/12/8
 */
public class ChatServer {
    private final static Logger log = LogManager.getLogger(ChatServer.class);

    private int port = 80;

    public ChatServer(int port) {
        this.port = port;
    }

    /**
     * 启动服务
     */
    public void start() {
        // BOSS线程
        EventLoopGroup bossGroup = new NioEventLoopGroup();

        // Worker线程
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {

            // 启动引擎
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();

                            // --------- 支持自定义socket ---------
                            pipeline.addLast(new IMEncoder());
                            pipeline.addLast(new IMDecoder());
                            pipeline.addLast(new SocketHandler());

                            // --------- 支持http ---------
                            // 解码、编码HTTP
                            pipeline.addLast(new HttpServerCodec());
                            pipeline.addLast(new HttpObjectAggregator(64 * 1024));

                            // 用于处理文件流
                            pipeline.addLast(new ChunkedWriteHandler());
                            pipeline.addLast(new HttpHandler());

                            // --------- 支持web socket ---------
                            pipeline.addLast(new WebSocketServerProtocolHandler("/im"));
                            pipeline.addLast(new WebSocketHandler());
                        }
                    });


            // 等待客户端连接
            ChannelFuture future = bootstrap.bind(port).sync();
            System.out.println("Start server: " + port);
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }


    public static void main(String[] args) throws IOException {
        new ChatServer(80).start();
    }
}
